/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass;

import com.inspur.edp.bff.api.manager.IFSManager;
import com.inspur.edp.bff.core.manager.builtinimpl.BffBuiltInManager;
import com.inspur.edp.bff.designtime.generator.core.mgrimpl.BeActionMethodGenerator;
import com.inspur.edp.bff.designtime.generator.core.mgrimpl.VmActionMethodGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.changesergen.BffEntityDataChangeSerGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.dataconverter.BffEntityDataSerializerGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.dataconverter.EntitySerializerGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.FSMgrGeneratorContext;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.methodgenerators.*;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.methodgenerators.createdatamethod.CreateDataMethodGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.methodgenerators.getchangeconvertormethod.GetChangeConvertorMethodGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.methodgenerators.getchangeconvertormethod.GetChangeDeSerGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.methodgenerators.getchangeconvertormethod.GetChangeSerGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.methodgenerators.getdataconvertormethod.GetDataConvertorMethodGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.methodgenerators.getvonodecode.GetVoNodeCodeMethodGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.propertygenerators.SourceConfigPropGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.mgrImplclass.propertygenerators.VoIdPropGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.request.RequestConvertGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.request.RequestInfoGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.response.ResponseConvertGenerator;
import com.inspur.edp.bff.designtime.generator.core.rtgen.managergenerator.response.ResponseInfoGenerator;
import com.inspur.edp.caf.generator.BaseGenerator;
import com.inspur.edp.caf.generator.baseInfo.TypeInfo;
import com.inspur.edp.caf.generator.item.ClassGeneratorContext;
import com.inspur.edp.caf.generator.method.ClassMethodGenerator;
import com.inspur.edp.caf.generator.property.ClassPropertyGenerator;
import com.inspur.edp.cef.designtime.api.variable.CommonVariableEntity;
import com.inspur.edp.cef.gencommon.MediateType;
import com.inspur.edp.cef.generator.coreGenerator.base.mgrGenerator.EntityManagerImplGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.mgrGenerator.method.GetAccessorCreatorGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.mgrGenerator.property.BufferManagerPropertyGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.mgrGenerator.property.ChangesetPropGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.serializer.changeser.ChangeSerGenerator;
import com.inspur.edp.cef.generator.coreGenerator.base.serializer.dataser.CefDataSerGenerator;
import com.inspur.edp.cef.generator.overall.GeneratorUtil;
import com.inspur.edp.cef.generator.repository.common.IntermediateType;
import com.inspur.edp.formserver.viewmodel.action.MappedBizAction;
import com.inspur.edp.formserver.viewmodel.action.MappedCdpAction;
import com.inspur.edp.formserver.viewmodel.action.ViewModelAction;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class FSMgrImplGenerator extends EntityManagerImplGenerator {
    private FSMgrGeneratorContext mgrGenContext;

    public FSMgrImplGenerator(FSMgrGeneratorContext mgrGenContext) {
        super(mgrGenContext);
        this.mgrGenContext = mgrGenContext;
    }

    protected FSMgrImplGenContext getContext() {
        return (FSMgrImplGenContext) ((super.getContext() instanceof FSMgrImplGenContext) ? super.getContext() : null);
    }

    @Override
    protected ClassGeneratorContext createClassInfoContext() {
        FSMgrImplGenContext context = new FSMgrImplGenContext(mgrGenContext);
        return context;
    }

    @Override
    protected String getName() {
        return GeneratorUtil.getName(getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext().getVm().getCode()) + "manager";
    }

    @Override
    protected List<ClassMethodGenerator> getMgrActionGenerators() {
        return null;
    }

    @Override
    protected void doInitialize() {
        super.doInitialize();
        mgrGenContext.setImplClassGenContext(getContext());
        getContext().setMgrImplType(new MediateType(mgrGenContext.getProjContext().getNameSpace(), getName()));
    }

    @Override
    protected ArrayList<TypeInfo> addParentInterfaces() {
        super.addParentInterfaces();
        ArrayList<TypeInfo> list = new ArrayList<TypeInfo>();; // = super.addParentInterfaces();
//        if (list == null)
//            list = new ArrayList<TypeInfo>();
        //String mgrInterfaceName = getContext().getMgrGenContext().getInterfaceContext().getInterfaceName();
        MediateType mgrAllInterfaceType = mgrGenContext.getFSGeneratorContext().getVmGenContext().getMgrAllInterfaceType();
        if (mgrAllInterfaceType != null) {
            list.add(new TypeInfo(mgrAllInterfaceType.getFullName()));
        }
//        list.add(new TypeInfo(mgrGenContext.getFSGeneratorContext().getVmGenContext().getMgrInterfaceType().getFullName()));
//        types.add(new TypeInfo(mgrGenContext.getFSGeneratorContext().getParentType().getInterfaceType()));
        list.add(new TypeInfo(IFSManager.class));
        return list;
    }


//    @Override
//    protected ArrayList<TypeInfo> addParentInterfaces() {
//        ArrayList<TypeInfo> list = super.addParentInterfaces();
//        if (list == null)
//            list = new ArrayList<TypeInfo>();
//        //String mgrInterfaceName = getContext().getMgrGenContext().getInterfaceContext().getInterfaceName();
//        MediateType mgrAllInterfaceType = mgrGenContext.getFSGeneratorContext().getVmGenContext().getMgrAllInterfaceType();
//        if (mgrAllInterfaceType != null) {
//            list.add(new TypeInfo(mgrAllInterfaceType.getFullName()));
//        }
//        list.add(new TypeInfo(mgrGenContext.getFSGeneratorContext().getVmGenContext().getMgrInterfaceType().getFullName()));
////        types.add(new TypeInfo(mgrGenContext.getFSGeneratorContext().getParentType().getInterfaceType()));
//        list.add(new TypeInfo(IFSManager.class));
//        return list;
//    }

    @Override
    protected Class getImplParentClassType() {
        return BffBuiltInManager.class;
    }

//    @Override
//    protected ArrayList<String> addGeneratedParentInterfaces() {
//        getContext(). getProjectInfo().AddGeneratedUsingList(Context.getMgrGenContext().getInterfaceContext().GetInterfaceNamespace());
//        String mgrInterfaceName = Context.getMgrGenContext().getInterfaceContext().GetInterfaceName();
//        return new ArrayList<String>(Arrays.asList(new String[]{mgrInterfaceName}));
//    }

    @Override
    protected void addExtendEntityMethodGenerator(ArrayList<ClassMethodGenerator> generators) {
        ArrayList<ClassMethodGenerator> list = new ArrayList<ClassMethodGenerator>();
        list.add(getCreateDataMethodGenerator());

        //TODO 這個方法替換為下面兩個
        list.add(getChangeConvertorMethodGenerator());
//        list.add(new GetChangeSerGenerator(getContext()));
//        list.add(new GetChangeDeSerGenerator(getContext()));

        list.add(getDataConvertorGenerator());

        TypeInfo dvType = getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext().getDefaultValueType();

        if(!mgrGenContext.getFSGeneratorContext().getVmGenContext().getVm().getIsVirtual()){
            TypeInfo dvConvertType = getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext().GetDefaultValueConvertorType();
            list.add(new GetDefaultValueConGenerator(getContext(), dvConvertType));
        }

        list.add(new GetDefaultValueTypeMethodGenerator(dvType, getContext()));

        list.add(getCreateChildDataMethodGenerator());
        list.add(new GetBECodeFromVMMethodGenerator(getContext()));
        list.add(new GetVMCodeFromBEMethodGenerator(getContext()));
        // list.Add(new GetElementHelpMethodGenerator(this.Context));
//        list.add(new GetHelpIdGenerator(getContext()));
        list.add(new GetHelpConfigMethodGenerator(getContext()));
//        list.add(new GetHelpActionGenerator(getContext()));
        list.add(new GetAssemblerMgrGenerator(getContext()));
        // todo 不再生成序列化和反序列化，直接调用框架
        //list.add(new GetDataSerizlizeGenerator(getContext()));
        CommonVariableEntity variableEntity = mgrGenContext.getFSGeneratorContext().getVmGenContext().getVm().getVariables();
        if(variableEntity != null && (variableEntity.getContainElements().size() > 0 ||
                (variableEntity.getDtmAfterModify() != null && variableEntity.getDtmAfterModify().size() > 0)))
            list.add(new CreateVariableManagerMethodGenerator(getContext()));

        // todo 不再生成序列化和反序列化，直接调用框架
       // list.add(new GetDataDeSerizlizeGenerator(getContext()));

        // GetChangeInfoType()
        //Class changeInfoType = getChangeInfoTypeName(type);
        list.add(new GetChangeInfoTypeMethodGenerator(getContext()));

        //public virtual Type GetRequsetType()
        list.add(new GetRequestTypeGenerator(getContext()));
        //public virtual Type GetResponseType()
        list.add(new GetResponseTypeGenerator(getContext()));

        //list.Add(new GetAccessorCreatorGenerator(getContext()));

//        FilterConvertorAttribute filterAttribute = (FilterConvertorAttribute) type.getAnnotation(FilterConvertorAttribute.class);
        if (mgrGenContext.getFSGeneratorContext().getVmGenContext().getVm().getIsGenFilterConvertor()) {
            list.add(new GetFilterConvertorMethodGenerator(getContext()));
        }

        list.add(new CreateEntityGenerator(mgrGenContext));
        list.add(new AddExtendsGenerator(getContext()));
        list.add(new GetVoNodeCodeMethodGenerator(getContext()));
        //TODO 集成后应该不需要了
        //addExtendMethodGenerators(list);
        list.add(new GetRootEntityPropMethodGenerator(getContext()));

        // todo 不再生成序列化和反序列化，直接调用框架
        //list.add(new GetChangeSerGenerator(getContext()));
        //list.add(getChangeDeserializerGenerator());
        list.add(new BffGetModelInfosGenerator(mgrGenContext));

        list.add(new GetResponseConvertorGenerator(getContext()));
        generators.addAll(list);

        AddExtendMethodGenerators(generators);
    }
    private TypeInfo getChangeInfoTypeName() {

        return getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext().getChangeConvertorType();

//        ChangeConvertorAttribute changeConvertorAttribute = (ChangeConvertorAttribute) implType.getAnnotation(ChangeConvertorAttribute.class);//<ChangeConvertorAttribute>GetCustomAttribute();
//        if (changeConvertorAttribute == null) {
//            return null;
//        }
//        Class changeInfoType = changeConvertorAttribute.entityType();
//        return changeInfoType;
    }

    protected ClassMethodGenerator getChangeDeserializerGenerator() {
        return new GetChangeDeSerGenerator(getContext());
    }

    private ClassMethodGenerator getCreateDataMethodGenerator() {
        return new CreateDataMethodGenerator(getContext(), mgrGenContext.getFSGeneratorContext().getVmGenContext().getVm().getMainObject());
    }

    private ClassMethodGenerator getCreateChildDataMethodGenerator() {
        return new CreateChildDataMethodGenerator(getContext());
    }

    private ClassMethodGenerator getChangeConvertorMethodGenerator() {
        return new GetChangeConvertorMethodGenerator(getContext());
    }

    private ClassMethodGenerator getDataConvertorGenerator() {

        return new GetDataConvertorMethodGenerator(getContext());
    }

    private void AddExtendMethodGenerators(java.util.ArrayList<ClassMethodGenerator> list) {
    for (ViewModelAction vmAction : getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext().getVm().getActions()) {
      switch (vmAction.getType()) {
        case BEAction:
          BeActionMethodGenerator gen = new BeActionMethodGenerator(
              (MappedBizAction) ((vmAction instanceof MappedBizAction) ? vmAction : null),
              getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext(),
              getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext().getMetadataPool());
            list.add(gen);
          break;
        case VMAction:
          VmActionMethodGenerator vmActionGen = new VmActionMethodGenerator(
              (MappedCdpAction) vmAction, getContext().getMgrGenContext().getFSGeneratorContext().getVmGenContext().getMetadataPool(),
              getContext().getMgrGenContext().getFSGeneratorContext());
            list.add(vmActionGen);
          break;
      }
    }
    }

    @Override
    protected void addExtendPropertyGenerator(ArrayList<ClassPropertyGenerator> generators) {
        generators.add(new VoIdPropGenerator(getContext()));

//        String className = getContext().getMgrGenContext().getFSGeneratorContext().getSouceConfigType().getClassName();
        SourceConfigPropGenerator sourceConfig = new SourceConfigPropGenerator(getContext());
        generators.add(sourceConfig);

    }

    @Override
    protected BufferManagerPropertyGenerator getBufferPropGenerator() {
        return null;
    }

    @Override
    protected ChangesetPropGenerator getChangesetPropGenerator() {
        return null;
    }

    @Override
    protected void afterGenerate() {
        super.afterGenerate();
        MediateType type = getContext().getMgrImplType();
        getContext().getMgrGenContext().getFSGeneratorContext().getFsIntermediateTypeInfo()
                .setFSMangerImplType(new IntermediateType(type.getClassName(), type.getNamespace()));
        //new IntermediateType(GetName(), GetNameSpace());
    }

    @Override
    protected ArrayList<ClassMethodGenerator> createConstructorGenerators() {
//        MgrImplConstructorGenerator generator = new MgrImplConstructorGenerator(getName());
        return new ArrayList<>(Arrays.asList(
                new ClassMethodGenerator[]{ new MgrImplCtorGenerator(getName())}));
    }

    @Override
    protected ArrayList<BaseGenerator> createClassExtendChildGenrators() {
        ArrayList<BaseGenerator> childGens = super.createClassExtendChildGenrators();
        if (childGens == null) {
            childGens = new ArrayList<BaseGenerator>();
        }

        TypeInfo changeInfoType = getChangeInfoTypeName();
        //requestInfo
        childGens.add(new RequestInfoGenerator(getContext()));
        //requestConvertor
        childGens.add(new RequestConvertGenerator(getContext(), changeInfoType));
        //responseInfo
        childGens.add(new ResponseInfoGenerator(getContext()));
        //responseConvertor
        childGens.add(new ResponseConvertGenerator(getContext(), changeInfoType));

        // todo 不再生成序列化和反序列化，直接调用框架
        childGens.add(new EntitySerializerGenerator((FSMgrGeneratorContext) ParentContext));
        //childGens.add(new BffEntityDataSerializerGenerator(ParentContext));
        //childGens.add(new BffEntityDataChangeSerGenerator(ParentContext));
        return childGens;
    }


//    @Override
//    protected ClassMethodGenerator getChangeSerializerGenerator() {
//        return new GetChangeSerGenerator(getContext());
//    }
//
//
//    @Override
//    protected MgrActionGenerator getMgrActionGenerator(Class implType, Method info) {
//        return new ExtendMethodGenerator(getContext(), info, implType);
//    }

//    @Override
//    protected GetAccessorCreatorGenerator get_getAccessorCreatorGenerator() {
//        return null;
//    }
}
